package fr.umlv.jee.jawp.service.aws;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;

@SuppressWarnings("serial")
public class Aws implements Serializable {

  /*
   * Your AWS Access Key ID, as taken from the AWS Your Account page.
   */
  private String AWS_ACCESS_KEY_ID;
  private String AWS_SECRET_KEY;
  private String AWS_ASSOCIATED_TAG;
  private String ENDPOINT;

  /*
   * Use one of the following end-points, according to the region you are
   * interested in:
   * 
   * US: ecs.amazonaws.com CA: ecs.amazonaws.ca UK: ecs.amazonaws.co.uk DE:
   * ecs.amazonaws.de FR: ecs.amazonaws.fr JP: ecs.amazonaws.jp
   */

  private SignedRequestsHelper helper;

  private Map<String, String> params;
  private String paramService;
  private String paramVersion;
  private String paramOperation;
  private String paramResponseGroup;
  private String paramSearchIndex;

  private int totalResultsCount;
  private int totalPagesCount;
  private int currentPage;

  public Aws() {
    AWS_ACCESS_KEY_ID = "AKIAI45NN7FD7O7Y3G5Q";
    AWS_SECRET_KEY = "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";
    AWS_ASSOCIATED_TAG = "javamawebstop-20";
    ENDPOINT = "ecs.amazonaws.fr";

    try {
      helper = SignedRequestsHelper.getInstance(ENDPOINT, AWS_ACCESS_KEY_ID,
          AWS_SECRET_KEY, AWS_ASSOCIATED_TAG);
    } catch (Exception e) {
      e.printStackTrace();
      return;
    }

    /*
     * Set the default params
     */
    paramService = "AWSECommerceService";
    paramVersion = "2011-08-01";
    paramOperation = "ItemSearch";
    // paramResponseGroup = "Small";
    paramResponseGroup = "ItemAttributes,Images,Offers"; // ",Images,Reviews,ItemAttributes";//,EditorialReview";
    paramSearchIndex = "All";
    params = new HashMap<String, String>();
  }

  public void setSearchIndex(String searchIndex) {
    paramSearchIndex = searchIndex;
  }

  public void setOperation(String searchIndex) {
    paramOperation = searchIndex;
  }

  public void prepareParams() {
    params.clear();
    params.put("Service", paramService);
    params.put("Version", paramVersion);
    params.put("Operation", paramOperation);
    params.put("ResponseGroup", paramResponseGroup);
    params.put("SearchIndex", paramSearchIndex);
  }

  public void prepareParams(Map<String, String> otherParams) {
    params.clear();
    params.put("Service", paramService);
    params.put("Version", paramVersion);
    params.put("Operation", paramOperation);
    params.put("ResponseGroup", paramResponseGroup);
    params.put("SearchIndex", paramSearchIndex);

    for (Iterator<String> param = otherParams.keySet().iterator(); param
        .hasNext();) {
      String key = param.next();
      String value = otherParams.get(key);
      params.put(key, value);
    }
  }

  public void calculatePagination(Document doc) {

    if (paramOperation.equals("ItemSearch")) {
      totalResultsCount = Integer.parseInt(ParserXML.getNodeValue(doc,
          "TotalResults"));
      totalPagesCount = Integer.parseInt(ParserXML.getNodeValue(doc,
          "TotalPages"));
      System.out.println("Total Result = " + totalResultsCount
          + " Total Pages = " + totalPagesCount);
    }

  }

  public Document requestURL(String requestUrl) {
    try {
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.parse(requestUrl);
      calculatePagination(doc);
      return doc;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public String parsePrice(String price) {
    
    return "";
  }

  public List<Map<String, String>> findArticleByItemID(String itemID) {
    List<Map<String, String>> article = null;
    Map<String, String> otherParams = new HashMap<String, String>();
    otherParams.put("ItemId", itemID);

    // we set up the correct operation
    setOperation("ItemLookup");

    prepareParams(otherParams);

    // When IdType equals ASIN, SearchIndex cannot be present
    params.remove("SearchIndex");

    String requestUrl = helper.sign(params);
    Document doc = requestURL(requestUrl);

    System.out.println("Query: " + requestUrl);

    article = ParserXML.findListItem(doc);

    return article;
  }

  public List<Map<String, String>> findArticleByKeyword(String keyword) {
    List<Map<String, String>> article = null;
    Map<String, String> otherParams = new HashMap<String, String>();
    otherParams.put("Keywords", keyword);

    // we set up the correct operation
    setOperation("ItemSearch");

    prepareParams(otherParams);
    String requestUrl = helper.sign(params);
    Document doc = requestURL(requestUrl);

    System.out.println("Query: " + requestUrl);

    article = ParserXML.findListItem(doc);

    return article;
  }

  public List<Map<String, String>> findArticleByKeyword(String keyword,
      String typeProcuct) {
    /*
     * searchIndex doit être parmi les listes Book, Classica, DVD, Electronics,
     * ForeignBooks, ...
     */
    List<Map<String, String>> article = null;
    Map<String, String> otherParams = new HashMap<String, String>();
    otherParams.put("Keywords", keyword);
    otherParams.put("SearchIndex", typeProcuct);

    // we set up the correct operation
    setOperation("ItemSearch");

    prepareParams(otherParams);
    String requestUrl = helper.sign(params);
    Document doc = requestURL(requestUrl);

    System.out.println("Query: " + requestUrl);

    currentPage = 0;

    article = ParserXML.findListItem(doc);

    return article;
  }

  public String getAWS_ACCESS_KEY_ID() {
    return AWS_ACCESS_KEY_ID;
  }

  public void setAWS_ACCESS_KEY_ID(String aWS_ACCESS_KEY_ID) {
    AWS_ACCESS_KEY_ID = aWS_ACCESS_KEY_ID;
  }

  public String getAWS_SECRET_KEY() {
    return AWS_SECRET_KEY;
  }

  public void setAWS_SECRET_KEY(String aWS_SECRET_KEY) {
    AWS_SECRET_KEY = aWS_SECRET_KEY;
  }

  public String getAWS_ASSOCIATED_TAG() {
    return AWS_ASSOCIATED_TAG;
  }

  public void setAWS_ASSOCIATED_TAG(String aWS_ASSOCIATED_TAG) {
    AWS_ASSOCIATED_TAG = aWS_ASSOCIATED_TAG;
  }

  public String getENDPOINT() {
    return ENDPOINT;
  }

  public void setENDPOINT(String eNDPOINT) {
    ENDPOINT = eNDPOINT;
  }

  public SignedRequestsHelper getHelper() {
    return helper;
  }

  public void setHelper(SignedRequestsHelper helper) {
    this.helper = helper;
  }

  public Map<String, String> getParams() {
    return params;
  }

  public void setParams(Map<String, String> params) {
    this.params = params;
  }

  public String getParamService() {
    return paramService;
  }

  public void setParamService(String paramService) {
    this.paramService = paramService;
  }

  public String getParamVersion() {
    return paramVersion;
  }

  public void setParamVersion(String paramVersion) {
    this.paramVersion = paramVersion;
  }

  public String getParamOperation() {
    return paramOperation;
  }

  public void setParamOperation(String paramOperation) {
    this.paramOperation = paramOperation;
  }

  public String getParamResponseGroup() {
    return paramResponseGroup;
  }

  public void setParamResponseGroup(String paramResponseGroup) {
    this.paramResponseGroup = paramResponseGroup;
  }

  public String getParamSearchIndex() {
    return paramSearchIndex;
  }

  public void setParamSearchIndex(String paramSearchIndex) {
    this.paramSearchIndex = paramSearchIndex;
  }

  public int getTotalResultsCount() {
    return totalResultsCount;
  }

  public void setTotalResultsCount(int totalResultsCount) {
    this.totalResultsCount = totalResultsCount;
  }

  public int getTotalPagesCount() {
    return totalPagesCount;
  }

  public void setTotalPagesCount(int totalPagesCount) {
    this.totalPagesCount = totalPagesCount;
  }

  public int getCurrentPage() {
    return currentPage;
  }

  public void setCurrentPage(int currentPage) {
    this.currentPage = currentPage;
  }

  public List<Map<String, String>> findArticleByKeyword(String keyword,
      String searchIndex, int itemPage) {
    /*
     * searchIndex doit être parmi les listes Book, Classica, DVD, Electronics,
     * ForeignBooks, ...
     */
    List<Map<String, String>> article = null;
    Map<String, String> otherParams = new HashMap<String, String>();
    otherParams.put("Keywords", keyword);
    otherParams.put("SearchIndex", searchIndex);
    otherParams.put("ItemPage", Integer.toString(itemPage));

    // we set up the correct operation
    setOperation("ItemSearch");

    prepareParams(otherParams);
    String requestUrl = helper.sign(params);
    Document doc = requestURL(requestUrl);

    System.out.println("Query: " + requestUrl);

    article = ParserXML.findListItem(doc);

    currentPage = itemPage;

    return article;
  }

  public List<Map<String, String>> findArticleNextPage(int itemPage) {

    if (itemPage <= 0) {
      itemPage = 1;
    }
    if (itemPage >= totalPagesCount) {
      itemPage = totalPagesCount;
    }

    List<Map<String, String>> article = null;

    params.put("ItemPage", Integer.toString(currentPage));

    String requestUrl = helper.sign(params);
    Document doc = requestURL(requestUrl);

    System.out.println("Query: " + requestUrl);

    article = ParserXML.findListItem(doc);

    currentPage = itemPage;

    return article;
  }

  public List<Map<String, String>> findArticleNextPage() {

    currentPage = (currentPage % totalPagesCount) + 1;
    return findArticleNextPage(currentPage);
  }
}
